#ifndef _RING_BUFFER_H
#define _RING_BUFFER_H

#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>

/**
 * @brief Ring buffer structure
 */
typedef struct {
    uint8_t *buffer;  /**< Pointer to the buffer memory */
    size_t head;      /**< Index of the head (read position) */
    size_t tail;      /**< Index of the tail (write position) */
    size_t capacity;  /**< Total capacity of the buffer */
    bool dynamic;     /**< Indicates whether the buffer supports dynamic expansion */
} ring_buffer_t;

/**
 * @brief Initializes a fixed-size ring buffer.
 * @param rb Pointer to the ring buffer structure.
 * @param size Size of the buffer in bytes.
 * @return 0 on success, -1 on failure.
 */
int ringbuf_init(ring_buffer_t *rb, size_t size);

/**
 * @brief Initializes a dynamically resizable ring buffer.
 * @param rb Pointer to the ring buffer structure.
 * @param size Initial size of the buffer in bytes.
 * @return 0 on success, -1 on failure.
 */
int ringbuf_init_dynamic(ring_buffer_t *rb, size_t size);

/**
 * @brief Frees the memory allocated for the ring buffer.
 * @param rb Pointer to the ring buffer structure.
 */
void ringbuf_free(ring_buffer_t *rb);

/**
 * @brief Clears the ring buffer, making it empty.
 * @param rb Pointer to the ring buffer structure.
 */
void ringbuf_clear(ring_buffer_t *rb);

/**
 * @brief Writes data into the ring buffer.
 * @param rb Pointer to the ring buffer structure.
 * @param data Pointer to the data to be written.
 * @param len Number of bytes to write.
 * @return Number of bytes actually written.
 */
size_t ringbuf_write(ring_buffer_t *rb, const uint8_t *data, size_t len);

/**
 * @brief Reads data from the ring buffer.
 * @param rb Pointer to the ring buffer structure.
 * @param data Pointer to the buffer to store read data.
 * @param len Number of bytes to read.
 * @return Number of bytes actually read.
 */
size_t ringbuf_read(ring_buffer_t *rb, uint8_t *data, size_t len);

/**
 * @brief Gets the number of bytes currently used in the buffer.
 * @param rb Pointer to the ring buffer structure.
 * @return Number of bytes used.
 */
size_t ringbuf_used_space(const ring_buffer_t *rb);

/**
 * @brief Gets the available free space in the buffer.
 * @param rb Pointer to the ring buffer structure.
 * @return Number of free bytes available.
 */
size_t ringbuf_free_space(const ring_buffer_t *rb);

/**
 * @brief Checks if the buffer is empty.
 * @param rb Pointer to the ring buffer structure.
 * @return true if the buffer is empty, false otherwise.
 */
bool ringbuf_is_empty(const ring_buffer_t *rb);

/**
 * @brief Checks if the buffer is full (in fixed-size mode).
 * @param rb Pointer to the ring buffer structure.
 * @return true if the buffer is full, false otherwise.
 */
bool ringbuf_is_full(const ring_buffer_t *rb);

#endif
